package com.csdj.t301.service;

import com.csdj.t301.entity.Menus;
import com.csdj.t301.mapper.MenusMapper;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

/**
 * author:cloud
 * date:2021/3/22 0022
 **/
@Service
public class MenuService {

    @Resource
    private MenusMapper menusMapper;

    private Logger log = Logger.getLogger("menu");

    /**
     * 获取所有的菜单，并用角色筛选
     * @param role
     * @return
     */
    public List<Menus> getAllMenus(String role){
        //查询所有菜单
        List<Menus> menus =  menusMapper.findAllMenus();
        if(menus.size()>0){
            //根据角色过滤菜单
            removeByRole(menus,role);
        }
        return menus;
    }

    /**
     * 添加一个菜单
     * @param menus
     * @return
     */
    @Transactional(rollbackFor = RuntimeException.class)
    public boolean add(Menus menus){
        int res = menusMapper.add(menus);
        if(menus.getTopId() == 0){
            //添加一个一级菜单
            return res>0;
        }
        //添加一个二级菜单
        if(res>0){
            //添加成功，检查一级菜单有没有相应的角色配置， 如果没有则要加上
            log.info("添加一个二级菜单");
            Menus topMenu = menusMapper.findById(menus.getTopId());
            String newTopeRoles = addRoles(topMenu.getRoles(),menus.getRoles());
            if(newTopeRoles.equals(topMenu.getRoles())){
                return res>0;
            }else{
                topMenu.setRoles(newTopeRoles);
                if(menusMapper.update(topMenu)>0){
                    return true;
                }else{
                    throw new RuntimeException("更新一级菜单失败");
                }
            }
        }else{
            //添加失败
            return res>0;
        }
    }

    /**
     * 修改菜单信息
     * @param menus
     * @return
     */
    public boolean update(Menus menus){
        //如果是一级菜单则不能修改角色， 一级菜单的角色都是由二级菜单决定的
        if(menus.getTopId() == 0){
            menus.setRoles(null);
            return menusMapper.update(menus)>0;
        }
        //如果是修改二级菜单，则还要计算一级菜单的角色
        if(menusMapper.update(menus)>0){
            //修改成功，查询同级菜单并计算一级菜单
            List<Menus> brotherMenus = menusMapper.findByTopId(menus.getTopId());
            String topRoles = getTopRoles(brotherMenus);
            Menus topMenus = menusMapper.findById(menus.getTopId());
            topMenus.setRoles(topRoles);
            return menusMapper.update(topMenus)>0;
        }
        //修改失败
        return false;
    }

    /**
     * 删除菜单
     * @param id
     * @return
     */
    public boolean delete(int id){
        Menus menus = menusMapper.findById(id);
        if(menus == null){
            log.info("菜单不存在");
            return false;
        }
        if(menusMapper.delete(id)>0){
            //修改上级菜单的角色
            List<Menus> list = menusMapper.findByTopId(menus.getTopId());
            String topRoles = getTopRoles(list);
            Menus topMenu = menusMapper.findById(menus.getTopId());
            topMenu.setRoles(topRoles);
            return menusMapper.update(topMenu)>0;
        }
        log.info("删除失败");
        return false;
    }


    /**
     * 根据角色删除没有菜单
     * @param menus
     * @param role
     */
    private void removeByRole(List<Menus> menus,String role){
        if(menus == null || menus.size() ==0 ) return;
        Iterator<Menus> iterator = menus.iterator();
        while (iterator.hasNext()){
            Menus menu = iterator.next();
            if(menu.getRoles().contains(role)){
                removeByRole(menu.getSubs(),role);
            }else{
                iterator.remove();
            }
        }
    }

    /**
     * 添加角色
     * 当添加二级菜单时 调用此方法， 更新一级菜单
     * @param topRoles
     * @param subRoles
     * @return
     */
    private String addRoles(String topRoles,String subRoles){
        StringBuilder roleSb = new StringBuilder(topRoles);
        for(String role:subRoles.split(",")){
            if(roleSb.indexOf(role)>-1){
               continue;
            }else{
                roleSb.append(",").append(role);
            }
        }
        return roleSb.toString();
    }

    /**
     * 由子菜单计算出父菜单角色
     * @param menus
     * @return
     */
    private String getTopRoles(List<Menus> menus){
        //利用set不能保存重复数据的特性
        Set<String> roleSet = new HashSet<>();
        for(Menus menu :menus){
            for(String role : menu.getRoles().split(",")){
                roleSet.add(role);
            }
        }
        return String.join(",",roleSet);
    }
}
